AffDots = LibStub( "AceAddon-3.0" ):NewAddon("AffDots","AceEvent-3.0")
AffDots.SharedMedia = LibStub("LibSharedMedia-3.0")

local _
local o
local me, class, spec
local timer, throttle		= 0, 0.1
local dot_damage, targets	= {},{}
AffDots.track				= {}
local in_combat				= false
local colors
local setburst				= false
local dmg_buff				= 1
AffDots.execute_percent		= 0
local spells = {
	corr			= GetSpellInfo(172),
	agony			= GetSpellInfo(980),
	ua				= GetSpellInfo(30108),
	coe				= GetSpellInfo(1490),
	poison			= GetSpellInfo(93068),
	shadowflame		= GetSpellInfo(47960),
	soulleech		= GetSpellInfo(108366),
	sacpact			= GetSpellInfo(108416),
	havoc			= GetSpellInfo(80240),
	backdraft		= GetSpellInfo(117896),
	fluidity		= GetSpellInfo(138002), --Fluidity +40%
	nutriment		= GetSpellInfo(140741), --Primal Nutriment +100% +10% per stack
	tricks			= GetSpellInfo(57934),	--Tricks of the Trade + 15%
	fearless		= GetSpellInfo(118977), --Fearless + 60%
	test			= GetSpellInfo(119050), --test
}
local DmgBuffEvents = {
	["SPELL_AURA_APPLIED"] = 1,
	["SPELL_AURA_REMOVED"] = 1,
	["SPELL_AURA_REFRESH"] = 1,
	["SPELL_AURA_APPLIED_DOSE"] = 1,
}
AffDots.tidyspells = {
	["Interface\\Icons\\Spell_Shadow_AbominationExplosion"] = {spell =	 172, pandemic =  9},
	["Interface\\Icons\\Spell_Shadow_CurseOfSargeras"]		= {spell =	 980, pandemic = 12},
	["Interface\\Icons\\Spell_Shadow_UnstableAffliction_3"] = {spell = 30108, pandemic =  7},
	["Interface\\Icons\\Spell_Shadow_AuraOfDarkness"]		= {spell =	 603, pandemic = 30},
	["Interface\\Icons\\Ability_Mage_WorldInFlames"]		= {spell =108686, pandemic =7.5},
	["Interface\\Icons\\Spell_Fire_Immolation"]				= {spell =	 348, pandemic =7.5},
}

local GetTime 				= GetTime
local GetMastery 			= GetMastery
local GetRangedHaste 		= GetRangedHaste
local GetSpellCritChance	= GetSpellCritChance
local GetSpellBonusDamage 	= GetSpellBonusDamage
local UnitDebuff 			= UnitDebuff
local UnitHealth 			= UnitHealth
local UnitHealthMax 		= UnitHealthMax
local UnitExists			= UnitExists
local UnitGUID				= UnitGUID
local UnitPower				= UnitPower
local math_floor			= math.floor

local m		= CreateFrame("Frame", "AffDotsTarget", UIParent)
local f		= CreateFrame("Frame",  "AffDotsFocus", UIParent)
local b		= CreateFrame("Frame",  "AffDotsBurst", UIParent)
b.bg	= b:CreateTexture()
b.text	= b:CreateFontString()
m:SetClampedToScreen(true)
f:SetClampedToScreen(true)
b:SetClampedToScreen(true)
m:SetFrameStrata("LOW")
f:SetFrameStrata("LOW")
b:SetFrameStrata("LOW")

local function Round(num) return math_floor(num+.5) end
local function SecondsRound(num)
	if num > 2 then return math_floor(num+.5)
	else return math_floor(num*10+.5)/10 end
end

function AffDots:CheckDmgBuffs()
	dmg_buff = 1
	local _,_,_,test 		= UnitAura("player",		spells.test, nil, "HARMFUL")
	local fluidity 			= UnitAura("player",	spells.fluidity, nil, "HARMFUL")
	local _,_,_,nutriment 	= UnitAura("player",   spells.nutriment)
	local tricks 			= UnitAura("player",	  spells.tricks)
	local fearless 			= UnitAura("player",	spells.fearless)
	if test 		then print( "test"); dmg_buff = 2 + (test-1) 			end
	if fluidity 	then print( "fluidity"); dmg_buff = 1.4 					end
	if nutriment 	then print("nutriment"); dmg_buff = 2 + (nutriment-1)*0.1 	end
	if fearless 	then print( "fearless"); dmg_buff = 1.6 					end
	if tricks 		then print(   "tricks"); dmg_buff = dmg_buff * 1.15			end
	AffDots.GetDotDmg()
end

function AffDots:FindColor(GUID,time_left,spell,pandemic)
	if not targets[GUID..spell] or not dot_damage[spell] then
		return 7
	end
	local color = 5
	local current 		= dot_damage[spell][1]
	local on_target 	= targets[GUID..spell][1]
	if		(on_target  < current and time_left <= pandemic) then color = 1
	elseif 	(on_target == current and time_left <= pandemic) then color = 2
	elseif	(on_target  > current and time_left <= pandemic) then color = 3
	elseif	(on_target*o.color_switch < current and time_left  > pandemic) then color = 4
	elseif	(on_target  > current and time_left  > pandemic) then color = 6
	end
	return color
end

local function OnMouseDown(self, button)
	if button == "LeftButton" and not self.isMoving and not setburst then
		self:StartMoving()
		self.isMoving = true
	elseif self == b and button == "RightButton" and setburst then
		AffDots:BurstDefaults()
	end
end

local function OnMouseUp(self, button)
	local p,_,rp, x, y = self:GetPoint()
	if		self == m then
		o.p = p; o.rp = rp; o.x = x; o.y = y
	elseif	self == f then
		o.focus_p = p; o.focus_rp = rp;	o.focus_x = x; o.focus_y = y
	elseif	self == b then
		o.burst.p = p; o.burst.rp = rp; o.burst.x = x; o.burst.y = y
	end
	if button == "LeftButton" and self.isMoving then
		self:StopMovingOrSizing()
		self:SetUserPlaced(false)
		self.isMoving = false
	end
end

m:SetScript("OnMouseDown", OnMouseDown)
f:SetScript("OnMouseDown", OnMouseDown)
b:SetScript("OnMouseDown", OnMouseDown)
m:SetScript("OnMouseUp", OnMouseUp)
f:SetScript("OnMouseUp", OnMouseUp)
b:SetScript("OnMouseUp", OnMouseUp)

function AffDots:ScaleAnimation(f, duration)
	local w = f.secw * duration
	f.f.scaleanimation:Stop()
	if w > o.bars.w then
		local delay = duration - o.bars.w/f.secw
		f.f.scale:SetStartDelay(delay)
		w = o.bars.w
		duration = o.bars.w/f.secw
	else
		f.f.scale:SetStartDelay(0)
	end
	f.f.statusbar:SetWidth(w)
	f.f.statusbar:Show()
    f.f.scale:SetDuration(duration)
    f.f.scale:SetScale(0,1)
	f.f.scaleanimation:Play()
end

function AffDots:Visibility()
	if(o.hide and not in_combat) then
		m:Hide(); if o.burst.enable then b:Hide() end
	else
		m:Show(); if o.burst.enable then b:Show() end
	end

	if(UnitGUID("focus") and o.focus and (in_combat or not o.hide)) then
		f:Show()
	else
		f:Hide()
	end

	m:SetMovable(not o.locked);m:EnableMouse(not o.locked)
	f:SetMovable(not o.locked);f:EnableMouse(not o.locked)
	b:SetMovable(not o.locked);b:EnableMouse(not o.locked)
end

---------------------------------------------------------------
local framepool, active_frames = {}, {}
function AffDots:ReleaseFrames()
	for i,f in pairs(active_frames) do
		f:Hide()
		tinsert(framepool, f)
	end
	wipe(active_frames)
end
function AffDots:GetFrame(parent)
	local f = tremove(framepool)
	if not f then
		f			= CreateFrame("Frame", nil, parent)
		f.statusbar	= f:CreateTexture(nil, "ARTWORK")
		f.bg		= f:CreateTexture(nil, "BACKGROUND")
		f.tick1		= f:CreateTexture(nil, "OVERLAY")
		f.tick2		= f:CreateTexture(nil, "OVERLAY")
		f.t1		= f:CreateFontString(nil, "OVERLAY")
		f.t2		= f:CreateFontString(nil, "OVERLAY")
		f.icon		= CreateFrame("Frame", nil, f)
		f.icon.file	= f.icon:CreateTexture(nil, "OVERLAY")
		f.cd		= CreateFrame("COOLDOWN", nil, f.icon)
		f.statusbar:SetPoint("TOPLEFT")
		f.bg:SetAllPoints(f)
		f.cd:SetAllPoints(f.icon)
		f.icon.file:SetAllPoints(f.icon)
		f.t1:SetFont("Fonts\\FRIZQT__.TTF",14,"OUTLINE")
		f.t2:SetFont("Fonts\\FRIZQT__.TTF",14,"OUTLINE")
		f.scaleanimation = f.statusbar:CreateAnimationGroup()
		f.scaleanimation:SetScript("OnFinished", function() f.statusbar:Hide() end)
		f.scale = f.scaleanimation:CreateAnimation("Scale")
		f.scale:SetOrder(1)
		f.scale:SetOrigin("TOPLEFT", 0, 0)
	else
		f:SetParent(parent)
	end
	tinsert(active_frames, f)
	f:Show()
	return f
end
---------------------------------------------------------------

function AffDots:Track(id,update,target,duration,tick,order,active,noprop)
	if not active then return end
	local spell = {}
	local parent
	if target == "target" then parent = AffDotsTarget else parent = AffDotsFocus end
	frame = AffDots:GetFrame(parent)
	if id > 0 then
		local n,r,i = GetSpellInfo(id)
		spell["pandemic" ]	= duration/3
		spell["name"	 ]	= n
		spell["rank"	 ]	= r
		spell["iconfile" ]	= i
		spell["spell"	 ]	= id
		spell["timer"	 ]	= 0
	end
	spell["tick"	 ]	= tick
	spell["duration" ]	= duration
	spell["f"		 ] 	= frame
	spell["target"	 ]	= target
	spell["order"	 ]	= order
	spell["update"   ]	= update
	if noprop then spell["noprop"] = true end
	tinsert(AffDots.track, spell)
end

function AffDots:InitFrames()
	if o.layout == "bars" then AffDots.FrameDraw = AffDots.Bar else AffDots.FrameDraw = AffDots.Box end
	local msize, fsize = 0, 0
	local font		= AffDots.SharedMedia:Fetch("font", o.font)
	local statusbar = AffDots.SharedMedia:Fetch("statusbar", o.bg)
	m:ClearAllPoints();f:ClearAllPoints()
	m:Show(); if o.focus then f:Show() end
	m:SetPoint(o.p, nil, o.rp, o.x, o.y)
	f:SetPoint(o.focus_p, nil, o.focus_rp, o.focus_x, o.focus_y)
	
	--layout
	for k,v in pairs(AffDots.track) do
		local c = AffDots.track[k]
		c.f.scaleanimation:Stop()
		c.dataold = {color = nil, bg = nil, tick = nil, t1 = nil, t2 = nil, setw = o.bars.w}
		c.datanew = {color = colors[1], bg = colors[8], tick = 0, t1 = "", t2 = "", setw = o.bars.w}
		if c.target == "target" then c.f:SetScale(o.scale) else c.f:SetScale(o.focus_scale) end
		c.f.t1:SetTextColor(unpack(o.color11))
		c.f.t2:SetTextColor(unpack(o.color11))
		c.f.icon:Hide();c.f.cd:Hide();c.f.t1:Hide();c.f.t2:Hide();c.f.tick1:Hide();c.f.tick2:Hide();c.f.statusbar:Hide();
		c.f:ClearAllPoints();c.f.icon:ClearAllPoints();c.f.t1:ClearAllPoints();c.f.t2:ClearAllPoints();
		c.f.t1:SetText("");c.f.t2:SetText("")
		c.f.bg:SetTexture(statusbar)
		c.f.bg:SetVertexColor(1, 1, 1, 1)
		if c.spell then
			if c.target == "target" then msize = msize + 1 else fsize = fsize + 1 end
			if o.layout == "horizontal" then
				c.f:SetSize(o.boxes_h.w,o.boxes_h.h)
				c.f:SetPoint("TOPLEFT", o.boxes_h.w*c.order, 0)
				c.f.icon.file:SetTexture(c.iconfile)
				c.f.icon:SetSize(o.boxes_h.icon_size,o.boxes_h.icon_size)
				c.f.icon.file:SetTexCoord(0.1,0.9,0.1,0.9)
				c.f.icon:SetPoint("TOP",0,-o.boxes_h.icon_position)
				c.f.t1:SetPoint("TOP",0,-o.boxes_h.text_position);c.f.t1:SetFont(font,o.large_text_size,"OUTLINE")
				if not o.hide_text then c.f.t1:Show() end
				if not o.hide_icons then c.f.icon:Show();c.f.cd:Show() end
			elseif o.layout == "vertical" then
				c.f:SetSize(o.boxes_v.w,o.boxes_v.h)
				c.f:SetPoint("TOPLEFT", 0, -o.boxes_v.h*c.order)
				c.f.icon.file:SetTexture(c.iconfile)
				c.f.icon:SetSize(o.boxes_v.icon_size,o.boxes_v.icon_size)
				c.f.icon.file:SetTexCoord(0.1,0.9,0.1,0.9)
				c.f.icon:SetPoint("LEFT",o.boxes_v.icon_position,0)
				c.f.t1:SetPoint("RIGHT",o.boxes_v.text_position-50,0);c.f.t1:SetFont(font,o.large_text_size,"OUTLINE")
				if not o.hide_text then c.f.t1:Show() end
				if not o.hide_icons then c.f.icon:Show();c.f.cd:Show() end
			elseif o.layout == "bars" then
				c.f:SetSize(o.bars.w,o.bars.h)
				c.f:SetPoint("TOPLEFT",0,-o.bars.h*c.order-(c.order*o.bars.margin))
				c.f.tick1:SetSize(1,o.bars.h)
				c.f.tick1:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
				c.f.tick1:SetVertexColor(1, 1, 1, 0.75);
				c.f.statusbar:SetHeight(o.bars.h)
				c.f.statusbar:SetTexture(statusbar)
				c.f.statusbar:SetVertexColor(0, 0, 0, o.transparency)
				if o.bars.proportional and not c.noprop then
					if c.tick > 0 and c.tick < o.bars.limit then
						c.f.tick1:SetPoint("LEFT",c.tick/o.bars.limit*o.bars.w,0)
					end
					c.secw = o.bars.w/o.bars.limit
				else
					if c.tick > 0 then
						c.f.tick1:SetPoint("LEFT",c.tick/c.duration*o.bars.w,0)
					end
					c.secw = o.bars.w/c.duration
				end
				c.f.tick2:SetSize(1,o.bars.h)
				c.f.tick2:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
				c.f.tick2:SetVertexColor(1, 1, 1, 0.75);
				c.f.icon.file:SetTexture(c.iconfile)
				c.f.icon:SetSize(o.bars.h,o.bars.h)
				c.f.icon.file:SetTexCoord(0.1,0.9,0.1,0.9)
				c.f.icon:SetPoint("LEFT",-o.bars.h,0)
				c.f.t1:SetPoint("CENTER",o.bars.text_position*(o.bars.w/100),0);
				c.f.t1:SetFont(font,o.large_text_size,"OUTLINE")
				c.f.t2:SetPoint("RIGHT",-3,0);
				c.f.t2:SetFont(font,o.large_text_size,"OUTLINE")
				c.f.bg:SetVertexColor(colors[8][1],colors[8][2],colors[8][3],o.transparency)
				if not o.hide_text then c.f.t1:Show();c.f.t2:Show() end
				if not o.hide_icons then c.f.icon:Show(); end
				if c.tick > 0 then c.f.tick1:Show() end
			end
		else
			local w
			if		o.layout == "horizontal" then
				w = o.boxes_h.w
			elseif	o.layout == "vertical" then
				w = o.boxes_v.w/2
			elseif	o.layout == "bars" then
				w = 40
			end
			c.f.statusbar:Hide()
			c.f:SetSize(w,20)
			c.f:SetPoint("TOPLEFT", 0, 22)
			c.f.t1:SetPoint("CENTER", 0, 0);c.f.t1:SetFont(font,o.small_text_size,"OUTLINE");c.f.t1:Show()
			if c.update == AffDots.Update.coe and o.hp then c.f:SetPoint("TOPLEFT", w, 22) end
			if c.update == AffDots.Update.sl then
				local position = 0
				if o.hp then position = position + 1 end
				if o.coe then position = position + 1 end
				c.f:SetPoint("TOPLEFT", w*position, 22)
			end
		end
	end

	if(o.layout == "horizontal") then
		m:SetSize(msize*o.boxes_h.w*o.scale, o.boxes_h.h*o.scale)
		f:SetSize(fsize*o.boxes_h.w*o.focus_scale, o.boxes_h.h*o.focus_scale)
	elseif(o.layout == "vertical") then
		m:SetSize(o.boxes_v.w*o.scale, msize*o.boxes_v.h*o.scale)
		f:SetSize(o.boxes_v.w*o.focus_scale, fsize*o.boxes_v.h*o.focus_scale)
	elseif(o.layout == "bars") then
		m:SetSize(o.bars.w*o.scale, msize*(o.bars.h+o.bars.margin)*o.scale)
		f:SetSize(o.bars.w*o.focus_scale, fsize*(o.bars.h+o.bars.margin)*o.focus_scale)
	end
	
	if o.hide_ui then
		AffDotsTarget:SetAlpha(0); AffDotsFocus:SetAlpha(0)
	else
		AffDotsTarget:SetAlpha(1); AffDotsFocus:SetAlpha(1)
	end

	if o.burst.enable then
		b:ClearAllPoints()
		b:Show()
		b:SetSize(o.burst.w, o.burst.h)
		b:SetPoint(o.burst.p, nil, o.burst.rp, o.burst.x, o.burst.y)
		b.bg:SetAllPoints(true)
		b.text:SetPoint("CENTER",0,0)
		b.text:SetFont(font,o.large_text_size,"OUTLINE")
		b.text:SetTextColor(o.color11[1],o.color11[2],o.color11[3])
		if o.burst.text then b.text:Show() else b.text:Hide() end
	else
		b:Hide()
	end
	AffDots:Visibility()
end

function AffDots:Tidy()
	local TidyPlates = TidyPlates
	local time_left, icon, spell, pandemic, GUID, c
	for plate in pairs(TidyPlates.NameplatesByVisible) do
		if not plate.extended.widgets.DebuffWidget then return false end
		GUID = plate.extended.unit.guid
		if GUID then
			for id,frame in pairs(plate.extended.widgets.DebuffWidget.AuraIconFrames) do
				icon = frame.Icon:GetTexture()
				if AffDots.tidyspells[icon] then
					spell = AffDots.tidyspells[icon].spell; pandemic = AffDots.tidyspells[icon].pandemic
					time_left = tonumber(frame.TimeLeft:GetText())
				end
				if not frame.affdots then
					frame.Icon:SetDrawLayer("ARTWORK")
					frame.Border:SetDrawLayer("BACKGROUND")
					frame.Border:SetSize(o.tidyplates.w,o.tidyplates.h)
					frame.Border:SetPoint("CENTER", 0, 0)
					frame.affdots = true
				end
				if spell and time_left then
					c = AffDots:FindColor(GUID,time_left,spell,pandemic)
					frame.Border:SetTexture(colors[c][1],colors[c][2],colors[c][3],o.tidyplates.transparency)
				else
					frame.Border:SetTexture(0,0,0,o.tidyplates.transparency)
				end
			end
		end
	end
end

function AffDots:Bar(f)
	if f.dataold.color ~= f.datanew.color then
		if o.color_text then
			f.f.t1:SetTextColor(f.datanew.color[1],f.datanew.color[2],f.datanew.color[3])
		end
		f.f.statusbar:SetVertexColor(f.datanew.color[1],f.datanew.color[2],f.datanew.color[3],o.transparency)
		f.dataold.color = f.datanew.color
	end
	if f.dataold.bg ~= f.datanew.bg then
		f.f.bg:SetVertexColor(f.datanew.bg[1],f.datanew.bg[2],f.datanew.bg[3],o.transparency)
		f.dataold.bg = f.datanew.bg
	end
	if f.dataold.t1 ~= f.datanew.t1 then
		f.f.t1:SetText(f.datanew.t1)
		f.dataold.t1 = f.datanew.t1
	end
	if f.dataold.t2 ~= f.datanew.t2 then
		f.f.t2:SetText(f.datanew.t2)
		f.dataold.t2 = f.datanew.t2
	end
	if f.dataold.tick ~= f.datanew.tick then
		if f.datanew.tick > 0 and f.secw*f.datanew.tick < o.bars.w then
			f.f.tick2:SetPoint("LEFT",f.secw*f.datanew.tick,0); f.f.tick2:Show()
		else
			f.f.tick2:Hide()
		end
		f.dataold.tick = f.datanew.tick
	end
	if f.datanew.setcd then
		local duration = f.datanew.expires - GetTime()
		AffDots:ScaleAnimation(f, duration)
		f.datanew.setcd = false
	end
	if f.datanew.hidecd then
		f.f.statusbar:Hide()
		f.datanew.hidecd = false
	end
	if f.dataold.setw ~= f.datanew.setw then
		f.f.statusbar:Show()
		f.f.statusbar:SetWidth(f.datanew.setw)
		f.dataold.setw = f.datanew.setw
	end
end

function AffDots:Box(f)
	if f.dataold.color ~= f.datanew.color then
		if o.color_text then
			f.f.t1:SetTextColor(f.datanew.color[1],f.datanew.color[2],f.datanew.color[3])
		end
		f.f.bg:SetTexture(f.datanew.color[1],f.datanew.color[2],f.datanew.color[3],o.transparency)
		f.dataold.color = f.datanew.color
	end
	if f.dataold.t1 ~= f.datanew.t1 then
		f.f.t1:SetText(f.datanew.t1)
		f.dataold.t1 = f.datanew.t1
	end
	if f.datanew.setcd and not o.hide_icons then
		f.f.cd:Show()
		f.f.cd:SetCooldown(f.datanew.expires-f.datanew.duration, f.datanew.duration)
		f.datanew.setcd = false
	end
	if f.datanew.hidecd then
		f.f.cd:Hide()
		f.datanew.hidecd = false
	end
end

local function onUpdate(self,elapsed)
    timer = timer + elapsed;
    if timer >= throttle then
		for k,v in pairs(AffDots.track) do
			AffDots.track[k].update(AffDots.track[k])
			AffDots:FrameDraw(AffDots.track[k])
		end
		if o.tidyplates.enable and TidyPlates then AffDots:Tidy() end
		if o.burst.enable then AffDots.Update.burst() end
        timer = 0
    end
end

SLASH_AFFDOTS1 = '/affdots'
function AffDotsHandler(msg, editBox)
	AffDots:GetLayoutOptions()
	AffDots:GetSpecOptions(class..spec)
	LibStub("AceConfigDialog-3.0"):Open("AffDots")
end
SlashCmdList["AFFDOTS"] = AffDotsHandler

function AffDots:MODIFIER_STATE_CHANGED(event,key,state)
	if key == o.burst.key and state == 1 then
		b:EnableMouse(true)
		setburst = true
	else
		b:EnableMouse(not o.locked)
		setburst = false
	end
end

function AffDots:PLAYER_REGEN_ENABLED()
	in_combat = false; AffDots:Visibility()
	local t = GetTime()
	for k,v in pairs(targets) do
		if targets[k][2] < t-120 then targets[k]=nil end
	end
end

function AffDots:PLAYER_REGEN_DISABLED()
	in_combat = true; AffDots:Visibility()
end

function AffDots:PLAYER_FOCUS_CHANGED()
	AffDots:Visibility()
end

function AffDots:SaveColors()
	o = self.db.profile
	colors = {o.color1,o.color2,o.color3,o.color4,o.color5,o.color6,o.color7,o.color8,o.color9,o.color10,o.color11}
end

function AffDots:BurstDefaults()
	if spec == 1 then
		o.burst.default[1] = dot_damage[172][1] + dot_damage[980][1] + dot_damage[30108][1]
	elseif spec == 2 then
		o.burst.default[2] = dot_damage[172][1]
	elseif spec == 3 then
		o.burst.default[3] = dot_damage[348][1]
	end
end

AffDots.Update = {
	dot	= function(f)
		local guid = UnitGUID(f.target)
		local _,_,_,_,_,duration,expires = UnitDebuff(f.target,f.name,f.rank,"player")
		if duration and guid and targets[guid..f.spell] then
			if(math.abs(expires-f.timer)>1) then
				if f.spell == 980 then
					if targets[guid..f.spell][4] == 0 then
						targets[guid.."980"][4] = expires
					elseif expires - targets[guid..f.spell][4] > 1 then
						targets[guid.."980"][4] = expires
						targets[guid.."980"][1] = dot_damage[980][1]
						targets[guid.."980"][3] = dot_damage[980][2]
					end
				end
				f.datanew.expires = expires
				f.datanew.duration = duration
				f.datanew.setcd = true
				f.timer = expires
			end
			f.datanew.color = colors[AffDots:FindColor(guid,expires - GetTime(),f.spell,f.pandemic)]
			f.datanew.tick = targets[guid..f.spell][3]
			f.datanew.t2 = SecondsRound(f.timer-GetTime())
			if o.reltext then
				f.datanew.t1 = Round(dot_damage[f.spell][1]*100/targets[guid..f.spell][1])
			elseif o.layout == "bars" then
				f.datanew.t1 = dot_damage[f.spell][1].."/"..targets[guid..f.spell][1]
			else
				f.datanew.t1 = dot_damage[f.spell][1].."\n"..targets[guid..f.spell][1]
			end
		else
			f.datanew.color = colors[7]
			f.datanew.t1 = 0
			f.datanew.t2 = ""
			f.datanew.tick = 0
			f.timer = 0
			f.datanew.hidecd = true
		end
	end,
	doom	= function(f)
		local guid = UnitGUID(f.target)
		local _,_,_,_,_,duration,expires = UnitDebuff(f.target,f.name,f.rank,"player")
		if duration and guid and targets[guid..f.spell] then
			if(math.abs(expires-f.timer)>1) then
				f.datanew.expires = expires
				f.datanew.duration = duration
				f.datanew.setcd = true
				f.timer = expires
			end
			f.datanew.color = colors[AffDots:FindColor(guid,expires - GetTime(),f.spell,f.pandemic)]
			f.datanew.tick = targets[guid..f.spell][3]
			f.datanew.t2 = SecondsRound(f.timer-GetTime())
			if o.reltext then
				f.datanew.t1 = Round(dot_damage[f.spell][1]*100/targets[guid..f.spell][1])..targets[guid..f.spell][4]
			elseif o.layout == "bars" then
				f.datanew.t1 = dot_damage[f.spell][1].."/"..targets[guid..f.spell][1]..targets[guid..f.spell][4]
			else
				f.datanew.t1 = dot_damage[f.spell][1].."\n"..targets[guid..f.spell][1]..targets[guid..f.spell][4]
			end
		else
			f.datanew.color = colors[7]
			f.datanew.t1 = 0
			f.datanew.t2 = ""
			f.datanew.tick = 0
			f.timer = 0
			f.datanew.hidecd = true
		end
	end,
	haunt = function(f)
		local shards = UnitPower("player", 7)
		local _,_,_,_,_,duration,expires = UnitDebuff(f.target, f.name,"","player")
		f.datanew.t1 = shards
		if not expires then
			if shards > 3 then
				f.datanew.color = colors[4]; f.datanew.bg = colors[4]
			else
				f.datanew.color = colors[7]; f.datanew.bg = colors[8]
			end
			f.datanew.hidecd = true
			f.datanew.t2 = ""
			f.timer = 0
		else
			f.datanew.color = colors[9]
			f.datanew.bg = colors[8]
			if(expires-f.timer>1) then
				f.datanew.expires = expires
				f.datanew.duration = duration
				f.datanew.setcd = true
				f.timer = expires
			end
			f.datanew.t2 = SecondsRound(f.timer-GetTime())
		end
	end,
	coe = function(f)
		local _,_,_,_,_,_,expires1 = UnitDebuff(f.target, spells.coe)
		local _,_,_,_,_,_,expires2 = UnitDebuff(f.target, spells.poison)
		local expires = expires1 or expires2
		if expires then
			local time_remaining = expires - GetTime()
			if 		time_remaining>60 	then f.datanew.t1 = (math_floor(time_remaining/60)+1).."m"
			elseif 	time_remaining>10	then f.datanew.t1 = "0:" ..math_floor(time_remaining)
			else 							 f.datanew.t1 = "0:0"..math_floor(time_remaining)
			end
			f.datanew.color = colors[9]; f.datanew.bg = colors[9]
		else
			f.datanew.t1 = ""
			f.datanew.color = colors[7]; f.datanew.bg = colors[8]
		end
	end,
	hp = function(f)
		f.datanew.color = colors[7]; f.datanew.bg = colors[8]
		if UnitExists(f.target) then
			local hp = Round(UnitHealth(f.target)*100/UnitHealthMax(f.target))
			f.datanew.t1 = hp
			if AffDots.execute_percent >= hp then
				f.datanew.color = colors[9]; f.datanew.bg = colors[9]
			end
		end
	end,
	sl = function(f)
		local _,_,_,_,_,_,_,_,_,_,_,_,_,_,sl = UnitAura("player", spells.soulleech)
		local _,_,_,_,_,_,_,_,_,_,_,_,_,_,sp = UnitAura("player", spells.sacpact)
		local bubble = 0
		if sl and sl > 0 then bubble = bubble + sl end
		if sp and sp > 0 then bubble = bubble + sp end
		if bubble > 0 then
			f.datanew.color = colors[9]; f.datanew.bg = colors[9]
			f.datanew.t1 = Round(bubble/1000).."k"
		else
			f.datanew.color = colors[7]; f.datanew.bg = colors[8]
			f.datanew.t1 = ""
		end
	end,
	burst = function()
		local current = 0
		local target = UnitGUID("target")
			
		if spec == 1 and target then
			local _,_,_,_,_,_,expires1 = UnitDebuff("target", spells.corr,nil,"player")
			local _,_,_,_,_,_,expires2 = UnitDebuff("target", spells.agony,nil,"player")
			local _,_,_,_,_,_,expires3 = UnitDebuff("target", spells.ua,nil,"player")
			if expires1 and targets[target.."172"] then current = current + targets[target.."172"][1] end
			if expires2 and targets[target.."980"] then current = current + targets[target.."980"][1] end
			if expires3 and targets[target.."30108"] then current = current + targets[target.."30108"][1] end
		elseif spec == 2 then
			current = dot_damage[172][1]
		elseif spec == 3 then
			current = dot_damage[348][1]
		end
		local damage = current/o.burst.default[spec]
		if damage > o.burst.switch then
			b.bg:SetTexture(o.burst.color[1],o.burst.color[2],o.burst.color[3],o.transparency)
		else
			b.bg:SetTexture(colors[7][1],colors[7][2],colors[7][3],o.transparency)
		end
		b.text:SetText(Round(damage*100))
	end,
	df = function(f)
		local power = UnitPower("player", 15)
		local color = 1
		if 		power <= o.demo.switch1 then color = 1
		elseif 	power <= o.demo.switch2 then color = 2
		elseif 	power <= o.demo.switch3 then color = 3
		elseif 	power <= o.demo.switch4 then color = 4
		elseif 	power <= o.demo.switch5 then color = 5
		end
		f.datanew.setw = o.bars.w*power/1000
		f.datanew.t1 = power
		f.datanew.color = o.demo["color"..color]
	end,
	hog = function(f)
		local currentCharges, maxCharges, timeLastCast, cooldownDuration = GetSpellCharges(105174)
		f.datanew.color = colors[7]; f.datanew.bg = colors[8]
		if currentCharges == maxCharges then
			f.datanew.t1 = currentCharges
			f.datanew.color = colors[9]; f.datanew.bg = colors[9]
		else
			local t = cooldownDuration-GetTime()+timeLastCast
			f.datanew.t1 = currentCharges.."/"..SecondsRound(t)
			if currentCharges == maxCharges - 1 and t < 5 then
				f.datanew.color = colors[9]; f.datanew.bg = colors[9]
			end
		end
		local _,_,_,_,_,_,expires = UnitDebuff("target", spells.shadowflame,nil,"player")
		if expires then
			if o.layout == "bars" then f.datanew.color = colors[1] end
			f.datanew.t2 = SecondsRound(expires-GetTime())
			f.datanew.expires = expires
			f.datanew.duration = duration
			f.datanew.setcd = true
		else
			f.datanew.t2 = ""
			f.datanew.hidecd = true
		end
	end,
	immo = function(f)
		local guid = UnitGUID(f.target)
		local _,_,_,_,_,duration,expires,_,_,_,id = UnitDebuff(f.target,f.name,f.rank,"player")
		if duration and guid and targets[guid..id] then
			if id == 348 and f.iconfile == spells.fnbImmoIcon then
				f.iconfile = spells.immoIcon
				f.f.icon.file:SetTexture(f.iconfile)
			elseif id == 108686 and f.iconfile == spells.immoIcon then
				f.iconfile = spells.fnbImmoIcon
				f.f.icon.file:SetTexture(f.iconfile)
			end
			if(math.abs(expires-f.timer)>1) then
				f.datanew.expires = expires
				f.datanew.duration = duration
				f.datanew.setcd = true
				f.timer = expires
			end
			f.datanew.color = colors[AffDots:FindColor(guid,expires - GetTime(),id,f.pandemic)]
			f.datanew.tick = targets[guid..id][3]
			f.datanew.t2 = SecondsRound(f.timer-GetTime())
			if o.reltext then
				f.datanew.t1 = Round(dot_damage[id][1]*100/targets[guid..id][1])
			elseif o.layout == "bars" then
				f.datanew.t1 = dot_damage[id][1].."/"..targets[guid..id][1]
			else
				f.datanew.t1 = dot_damage[id][1].."\n"..targets[guid..id][1]
			end
		else
			if f.iconfile ~= spells.immoIcon then
				f.iconfile = spells.immoIcon
				f.f.icon.file:SetTexture(f.iconfile)
			end
			f.datanew.color = colors[7]
			f.datanew.t1 = 0
			f.datanew.t2 = ""
			f.datanew.tick = 0
			f.timer = 0
			f.datanew.hidecd = true
		end
	end,
	embers = function(f)	
		local power = UnitPower("player", 14, true)
		local color = 1
		if 		power <= o.destro.switch1 then color = 1
		elseif 	power <= o.destro.switch2 then color = 2
		elseif 	power <= o.destro.switch3 then color = 3
		elseif 	power <= o.destro.switch4 then color = 4
		end
		f.datanew.setw = o.bars.w*power/40
		f.datanew.t1 = power
		f.datanew.color = o.destro["color"..color]
	end,
	conflag = function(f)
		local currentCharges, maxCharges, timeLastCast, cooldownDuration = GetSpellCharges(17962)
		f.datanew.bg = colors[8]
		if o.layout == "bars" then f.datanew.color = colors[3] else f.datanew.color = colors[7] end
		if currentCharges == maxCharges then
			f.datanew.color = colors[9]; f.datanew.bg = colors[9]
			f.datanew.t2 = ""
			f.datanew.hidecd = true
		else
			f.datanew.expires = timeLastCast+cooldownDuration
			f.datanew.duration = cooldownDuration
			f.datanew.setcd = true
			f.datanew.t2 = SecondsRound(cooldownDuration-GetTime()+timeLastCast)
		end
		f.datanew.t1 = currentCharges
	end,
	rof = function(f)
		local _,_,_,_,_,duration,expires = UnitAura("player",f.name,nil,"player")
		if expires then
			f.datanew.color = colors[9]
			f.datanew.t2 = SecondsRound(expires-GetTime())
			f.datanew.expires = expires
			f.datanew.duration = duration
			f.datanew.setcd = true
		else
			f.datanew.color = colors[7]
			f.datanew.t2 = ""
			f.datanew.hidecd = true
		end
	end,
	havoc = function(f)
		local _,_,_,count,_,duration,expires = UnitAura("player",spells.havoc)
		local cdstart, cdduration, cdenabled = GetSpellCooldown(spells.havoc)
		if count then
			f.datanew.t1 = count
			f.datanew.color = colors[9]
		else
			f.datanew.t1 = 0
			f.datanew.color = colors[7]
		end
		if(cdstart > 0 and cdduration > 1.5) then
			f.datanew.t2 = SecondsRound(cdstart + cdduration - GetTime())
			f.datanew.expires = cdstart + cdduration
			f.datanew.duration = cdduration
			f.datanew.setcd = true
		else
			f.datanew.color = colors[9]
			f.datanew.t2 = "Ready"
			f.datanew.hidecd = true
			f.datanew.setw = o.bars.w
		end
	end,
	draft = function(f)
		local _,_,_,count = UnitAura("player",spells.backdraft)
		if count then
			f.datanew.t1 = count
			f.datanew.color = colors[9]
			f.datanew.setw = o.bars.w*count/6
		else
			f.datanew.t1 = 0
			f.datanew.color = colors[7]
			f.datanew.hidecd = true
		end
	end,
}

local GetDotDmg = {
	function()
		local mastery, haste, crit, spd = GetMastery(), UnitSpellHaste("player"), GetSpellCritChance(6), GetSpellBonusDamage(6)
		if crit > 100 then crit = 100 end
	
		damage_bonus 		= (1+crit/100)*(1+(mastery*3.1)/100)
		tick_every 			= 2/(1+(haste/100))

		ticks 				= Round(24/tick_every)
		duration 			= ticks * tick_every
		damage				= ticks*(280+spd*0.26)*damage_bonus*dmg_buff
		dps					= Round(damage/duration)
		dot_damage[980]		= {Round(dps/100)/10, tick_every}

		ticks 				= Round(18/tick_every)
		duration 			= ticks * tick_every
		damage		 		= (1926+ticks*spd*0.2)*damage_bonus*dmg_buff
		dps					= Round(damage/duration)
		dot_damage[172]		= {Round(dps/100)/10, tick_every}

		ticks 				= Round(14/tick_every)
		duration 			= ticks * tick_every
		damage 				= (1792+ticks*spd*0.24)*damage_bonus*dmg_buff
		dps		 			= Round(damage/duration)
		dot_damage[30108]	= {Round(dps/100)/10, tick_every}
	end,
	function()
		local mastery, haste, crit, spd = GetMastery(), UnitSpellHaste("player"), GetSpellCritChance(6), GetSpellBonusDamage(6)
		if crit > 100 then crit = 100 end
	
		damage_bonus 		= (1+crit/100)*(1+(mastery)/100)
		bonus				= (1+crit/100)*(1+(mastery*3)/100)

		tick_every 			= 2/(1+(haste/100))
		ticks 				= Round(18/tick_every)
		duration 			= ticks * tick_every
		damage		 		= (1926+ticks*spd*0.2)*damage_bonus*dmg_buff
		dps					= Round(damage/duration)
		dot_damage[172]		= {Round(dps/100)/10, tick_every}

		tick_every 			= 15/(1+(haste/100))
		ticks 				= Round(60/tick_every)
		duration 			= ticks * tick_every
		damage		 		= (5340/ticks+spd*1.25)*bonus*ticks*dmg_buff
		dps					= Round(damage/duration)
		local c
		if crit == 100 then c = "c" else c = "" end
		dot_damage[603]		= {Round(dps/100)/10, tick_every, c}
	end,
	function()
		local mastery, haste, crit, spd = GetMastery(), UnitSpellHaste("player"), GetSpellCritChance(6), GetSpellBonusDamage(6)
		if crit > 100 then crit = 100 end
	
		damage_bonus 		= (1+crit/100)*(1+(mastery+1)/100)
		bonus				= (100+mastery*3)*0.35/100

		tick_every 			= 3/(1+(haste/100))
		ticks 				= Round(15/tick_every)
		duration 			= ticks * tick_every
		damage		 		= (1980+ticks*spd*0.371)*damage_bonus*dmg_buff
		dps					= Round(damage/duration)
		dot_damage[348]		= {Round(dps/100)/10, tick_every}
		dot_damage[108686]	= {Round(dps*bonus/100)/10, tick_every}
	end,
}

local CombatLog = {
	function(_,_,_,event,_,source_GUID,_,_,_,dest_GUID,_,_,_, ...)
		--if dest_GUID == me and DmgBuffEvents[event] then AffDots:CheckDmgBuffs() end
		if(source_GUID ~= me or (event ~= "SPELL_AURA_REFRESH" and event ~= "SPELL_AURA_APPLIED" and event ~= "SPELL_DAMAGE")) then return end
		spell = select(1, ...)
		if(event == "SPELL_AURA_APPLIED" or event == "SPELL_AURA_REFRESH") then
			if(spell == 30108) then
				targets[dest_GUID.."30108"] = {dot_damage[30108][1],GetTime(),dot_damage[30108][2]}
			elseif(spell == 172 or spell == 87389) then
				targets[dest_GUID.."172"] = {dot_damage[172][1],GetTime(),dot_damage[172][2]}
			elseif(spell == 980) then
				targets[dest_GUID.."980"] = {dot_damage[980][1],GetTime(),dot_damage[980][2],0}
			end
		elseif(event == "SPELL_DAMAGE" and spell == 77799) then
			targets[dest_GUID.."172"] = {dot_damage[172][1],GetTime(),dot_damage[172][2]}
			targets[dest_GUID.."30108"] = {dot_damage[30108][1],GetTime(),dot_damage[30108][2]}
		end
	end,
	function(_,_,_,event,_,source_GUID,_,_,_,dest_GUID,_,_,_, ...)
		--if dest_GUID == me and DmgBuffEvents[event] then AffDots:CheckDmgBuffs() end
		if(source_GUID ~= me or (event ~= "SPELL_AURA_REFRESH" and event ~= "SPELL_AURA_APPLIED" and event ~= "SPELL_DAMAGE")) then return end
		spell = select(1, ...)
		if(event == "SPELL_AURA_APPLIED" or event == "SPELL_AURA_REFRESH") then
			if(spell == 172) then
				targets[dest_GUID.."172"] = {dot_damage[172][1],GetTime(),dot_damage[172][2]}
			elseif(spell == 603) then
				targets[dest_GUID.."603"] = {dot_damage[603][1],GetTime(),dot_damage[603][2],dot_damage[603][3]}
			end
		elseif(event == "SPELL_DAMAGE" and (spell == 103964 or spell == 77799 or spell == 115422)) then
			targets[dest_GUID.."172"] = {dot_damage[172][1],GetTime(),dot_damage[172][2]}
		end
	end,
	function(_,_,_,event,_,source_GUID,_,_,_,dest_GUID,_,_,_, ...)
		--if dest_GUID == me and DmgBuffEvents[event] then AffDots:CheckDmgBuffs() end
		if(source_GUID ~= me or (event ~= "SPELL_AURA_REFRESH" and event ~= "SPELL_AURA_APPLIED" and event ~= "SPELL_DAMAGE")) then return end
		spell = select(1, ...)
		if(event == "SPELL_AURA_APPLIED" or event == "SPELL_AURA_REFRESH") then
			if(spell == 348) then
				targets[dest_GUID.."348"] = {dot_damage[348][1],GetTime(),dot_damage[348][2]}
			elseif(spell == 108686) then
				targets[dest_GUID.."108686"] = {dot_damage[108686][1],GetTime(),dot_damage[108686][2]}
			end
		elseif(event == "SPELL_DAMAGE" and spell == 77799) then
			targets[dest_GUID.."348"] = {dot_damage[348][1],GetTime(),dot_damage[348][2]}
			targets[dest_GUID.."108686"] = {dot_damage[108686][1],GetTime(),dot_damage[108686][2]}
		end
	end,
}

function AffDots:InitSpec()
	local e = 1
	for i=1,6 do
		local _,_,_,id,_ = GetGlyphSocketInfo(i)
		if id == 118778 then e = 1.5 end
	end
	AffDots:ReleaseFrames()
	wipe(AffDots.track)
	if spec == 1 then
		AffDots.execute_percent = 20;
		AffDots:Track(   172,	  AffDots.Update.dot, "target", 27*e,  9*e,	   o.aff.corr,					 true)
		AffDots:Track(   980,	  AffDots.Update.dot, "target", 36*e, 12*e,	  o.aff.agony,					 true)
		AffDots:Track( 30108,	  AffDots.Update.dot, "target", 21*e,  7*e,		 o.aff.ua,					 true)
		AffDots:Track( 48181,   AffDots.Update.haunt, "target",    8,  1.5,	  o.aff.haunt,		 o.aff.show_haunt)
		AffDots:Track( 	   0,	   AffDots.Update.hp, "target",    0,    0,				0,					 o.hp)
		AffDots:Track( 	   0,	  AffDots.Update.coe, "target",	   0,    0,				1,					o.coe)
		AffDots:Track( 	   0,	   AffDots.Update.sl, "target",	   0,    0,				2,					 o.sl)
		if o.focus then
		AffDots:Track(   172,	  AffDots.Update.dot,  "focus",	27*e,  9*e,	   o.aff.corr,					 true)
		AffDots:Track(   980,	  AffDots.Update.dot,  "focus",	36*e, 12*e,	  o.aff.agony,					 true)
		AffDots:Track( 30108,	  AffDots.Update.dot,  "focus",	21*e,  7*e,		 o.aff.ua,					 true)
		AffDots:Track( 	   0,	   AffDots.Update.hp,  "focus",	   0,    0,				0,	  				 o.hp)
		AffDots:Track( 	   0,	  AffDots.Update.coe,  "focus",	   0,    0,				1,	 				o.coe)
		end
	elseif spec == 2 then
		AffDots.execute_percent = 25;
		AffDots:Track(   172,	  AffDots.Update.dot, "target",	27*e,  9*e,	  o.demo.corr,					 true)
		AffDots:Track(   603,	 AffDots.Update.doom, "target",	90*e, 30*e,	  o.demo.doom,		 			 true)
		AffDots:Track(105174,	  AffDots.Update.hog, "target",	   6,    2,	   o.demo.hog,		  o.demo.show_hog)
		AffDots:Track(104315,	   AffDots.Update.df, "target",	   0,    0,		o.demo.df,	 	   o.demo.show_df, true)
		AffDots:Track( 	   0,	   AffDots.Update.hp, "target",    0,    0,				0,					 o.hp)
		AffDots:Track( 	   0,	  AffDots.Update.coe, "target",    0,    0,				1,					o.coe)
		AffDots:Track( 	   0,	   AffDots.Update.sl, "target",	   0,    0,				2,					 o.sl)
		if o.focus then
		AffDots:Track(   172,	  AffDots.Update.dot,  "focus", 27*e,  9*e,	  o.demo.corr,					 true)
		AffDots:Track(   603,	 AffDots.Update.doom,  "focus", 90*e, 30*e,	  o.demo.doom,					 true)
		AffDots:Track( 	   0,	   AffDots.Update.hp,  "focus",    0,    0,				0,					 o.hp)
		AffDots:Track( 	   0,	  AffDots.Update.coe,  "focus",    0,    0,				1,					o.coe)
		end
	elseif spec == 3 then
		AffDots.execute_percent = 20;
		AffDots:Track(   348,	 AffDots.Update.immo, "target", 22.5,  7.5,   o.destro.immo,				 true)
		AffDots:Track( 17962, AffDots.Update.conflag, "target",   12,    0,o.destro.conflag,o.destro.show_conflag)
		AffDots:Track(108647,  AffDots.Update.embers, "target",   40,    0, o.destro.embers, o.destro.show_embers, true)
		AffDots:Track(  5740,	  AffDots.Update.rof, "target",    7,    0,	   o.destro.rof,	o.destro.show_rof)
		AffDots:Track( 80240,	AffDots.Update.havoc, "target",	  25,   10,	 o.destro.havoc,  o.destro.show_havoc, true)
		AffDots:Track(117896,	AffDots.Update.draft, "target",	   0,    0,o.destro.backdraft,o.destro.show_backdraft, true)
		AffDots:Track( 	   0,	   AffDots.Update.hp, "target",    0,    0,				  0,				 o.hp)
		AffDots:Track( 	   0,	  AffDots.Update.coe, "target",    0,    0,				  1,				o.coe)
		AffDots:Track( 	   0,	   AffDots.Update.sl, "target",	   0,    0,				  2,				 o.sl)
		if o.focus then
		AffDots:Track(   348,	 AffDots.Update.immo,  "focus", 22.5,  7.5,	  o.destro.immo,				 true)
		AffDots:Track( 	   0,	   AffDots.Update.hp,  "focus",    0,    0,				  0,				 o.hp)
		AffDots:Track( 	   0,	  AffDots.Update.coe,  "focus",    0,    0,				  1,				o.coe)
		end
	end
	AffDots:InitFrames()
end

function AffDots:InitClass()
	spells.immoIcon		= select(3, GetSpellInfo(348))
	spells.fnbImmoIcon	= select(3, GetSpellInfo(108686))

	me = UnitGUID("player")
	AffDots:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
	AffDots:UnregisterEvent("COMBAT_RATING_UPDATE")
	AffDots:UnregisterEvent("SPELL_POWER_CHANGED")
	AffDots:UnregisterEvent("UNIT_STATS")
	AffDots:UnregisterEvent("PLAYER_DAMAGE_DONE_MODS")
	AffDots:UnregisterEvent("PLAYER_REGEN_ENABLED")
	AffDots:UnregisterEvent("PLAYER_REGEN_DISABLED")
	AffDots:UnregisterEvent("PLAYER_FOCUS_CHANGED")
	AffDots:UnregisterEvent("MODIFIER_STATE_CHANGED")
	AffDotsTarget:SetScript("OnUpdate", nil)
	AffDotsTarget:Hide(); AffDotsFocus:Hide(); AffDotsBurst:Hide()
	spec = GetSpecialization() or ""
	if (spec == 1 and o.aff.enabled) or (spec == 2 and o.demo.enabled) or (spec == 3 and o.destro.enabled) then
		AffDots.GetDotDmg = GetDotDmg[spec]
		AffDots.CombatLog = CombatLog[spec]
		AffDots:GetDotDmg()
		AffDots:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED", "CombatLog")
		AffDots:RegisterEvent("COMBAT_RATING_UPDATE", "GetDotDmg")
		AffDots:RegisterEvent("SPELL_POWER_CHANGED", "GetDotDmg")
		AffDots:RegisterEvent("UNIT_STATS", "GetDotDmg")
		AffDots:RegisterEvent("PLAYER_DAMAGE_DONE_MODS", "GetDotDmg")
		AffDots:RegisterEvent("PLAYER_REGEN_ENABLED")
		AffDots:RegisterEvent("PLAYER_REGEN_DISABLED")
		AffDots:RegisterEvent("PLAYER_FOCUS_CHANGED")
		AffDots:RegisterEvent("MODIFIER_STATE_CHANGED")
		AffDotsTarget:SetScript("OnUpdate", onUpdate)
		AffDots:InitSpec()
	end
end

function AffDots:OnInitialize()
	me = UnitGUID("player")
	AffDots:DefaultOptions()
	
	self.db.RegisterCallback(self, "OnProfileChanged", "InitClass")
    self.db.RegisterCallback(self, "OnProfileCopied", "InitClass")
    self.db.RegisterCallback(self, "OnProfileReset", "InitClass")

	self.options = self:OptionsTable()
    LibStub('LibDualSpec-1.0'):EnhanceDatabase(self.db, "AffDots")
    LibStub('LibDualSpec-1.0'):EnhanceOptions(self.options.args.profile, self.db)
	LibStub("AceConfig-3.0"):RegisterOptionsTable("AffDots", self.options)
	
	self:MigrateOptions()
	o = self.db.profile
	colors = {o.color1,o.color2,o.color3,o.color4,o.color5,o.color6,o.color7,o.color8,o.color9,o.color10,o.color11}

	class = select(2, UnitClass("player"))
	spec = GetSpecialization() or ""
	if class ~= "WARLOCK" then
		local loaded = LoadAddOn("AffDots"..class)
		if loaded then
			AffDots:InitClass()
		end
	else
		AffDots:RegisterEvent("PLAYER_TALENT_UPDATE", "InitClass")
		AffDots:InitClass()
	end
end

function  AffDots:OnEnable() end
function AffDots:OnDisable() end
function AffDots.FrameDraw() end
AffDots.targets = targets
AffDots.dot_damage = dot_damage